#include<string>
#include<iostream>
#include<sys/types.h>
#include<sys/ipc.h>
#include<unistd.h>
#include<sys/shm.h>
using namespace std;
string PATH="/home/hjh/shm";//共享内存的路径
string NAME="text";//共享内存的名称
int proj_id=0x66;//共享内存的项目ID
int shmsize=4096;//共享内存的大小
int gshmid=-1;//全局共享内存的ID
string CLIENT ="client";
string SERVER ="server";
class shm
{
private:
    void creat(string username)
    {
        cout<<"Create shared memory for "<<_username<<endl;
        cout << "Create shared memory for "<< _key << endl;
        if(username==SERVER)//如果是服务器，则创建共享内存
        {
            _shmid=shmget(_key,_shmsize,IPC_CREAT|IPC_EXCL|0666);//创建共享内存同时设置权
            cout<<_shmid<<endl;
            if(_shmid<0)
            {
                cout<<"Error: create shared memory failed!"<<endl;
                return;
            }
            cout<<"Create shared memory success!"<<endl;
        }
        else if(username==CLIENT)//如果是客户，则连接到共享内存
        {
            _shmid=shmget(_key,_shmsize,IPC_CREAT | 0666);//连接到共享内存
            cout<<_shmid<<endl;
            if(_shmid<0)
            {
                cout<<"Error: connect shared memory failed!"<<endl;
                return;
            }
            cout<<"Connect shared memory success!"<<endl;
        }
        else
        {
            cout<<"Error: username is not correct!"<<endl;
        }
    }
    void attch()//将进程和对应的共享内存联系起来
    {

        _shm_ptr=shmat(_shmid,nullptr,0);//将进程和共享内存联系起来
        if((long long)_shm_ptr<0)
        {
            perror(":");
            cout<<"Error: attach shared memory failed!"<<endl;
            return;
        }
        cout<<"Attach shared memory success!"<<endl;
    }
    void detach()//将进程和对应的共享内存解除联系
    {
        int n=shmdt(_shm_ptr);//将进程和共享内存解除联系
        if(n<0)
        {
            cout<<"Error: detach shared memory failed!"<<endl;
            return;
        }
        cout<<"Detach shared memory success!"<<endl;
    }
    void destroy()//销毁共享内存
    {
        //首先detch，然后再销毁共享内存
        detach();
        std::cout <<"_key" << _key << std::endl;
        int n=shmctl(_shmid,IPC_RMID,nullptr);//销毁共享内存
        if(n<0)
        {
            cout<<"Error: destroy shared memory failed!"<<endl; 
            return;
        }
        cout<<"Destroy shared memory success!"<<endl;
    }
public:
    shm(string username)
    :_username(username) 
    ,_shmid(gshmid)
    ,_shmsize(shmsize)
    ,_shm_ptr(nullptr)
    {
        _pathname = PATH+"/"+NAME;
        std::cout << "_pathname" << _pathname << std::endl;
        _key=ftok(_pathname.c_str(),proj_id);//获取共享内存的键值
    }
    void server_get()//创建一个共享内存
    {
        creat(_username);
        attch();
    }
    void client_get()
    {
        creat(_username);
        attch();
    }
    void* virtual_address()//获取共享内存的起始虚拟地址
    {
        cout<<"Virtual address of shared memory is:"<<_shm_ptr<<endl;
        return _shm_ptr;
    }
    int size()
    {
        return _shmsize;
    }
    ~shm()
    {
        destroy();
    }
private:
    string _pathname;//用于ftok函数的路径名
    key_t _key;//共享内存的键值
    string _username;//使用共享内存的是客户还是服务器
    void* _shm_ptr;//起始虚拟地址
    int _shmsize;//共享内存的大小
    int _shmid;//共享内存的ID
};